//
//  设计模式.h
//  面试题
//
//  Created by Toj on 8/13/21.
//

// MARK: - 什么叫设计模式?
/*
 设计模式: 在软件开发中重复出现的问题的解决方案.
 NOTE: 设计模式跟 MVC框架 不是一个东西
 */

// MARK: - 设计模式有那些?
/**
 * 二十三种设计模式
 * 1. 创建型模式
 * 2. 结构型模式
 * 3. 行为型模式
 */

// MARK: - 1. 创建型模式
// MARK: 1. 工厂方法模式(Factory Method Pattern)
/**
 * 定义一个用于创建对象的接口, 让子类决定实例化哪一个类.
 * 工厂方法使一个类的实例化延迟到其子类.
 * e.g.:
 * 项目种有需要展示不同的全屏广告, 有原生、admob激励、admob开屏、admob插页等广告类
 * 他们的共性: 全屏展示, 互斥显示.
 * 提供一个抽象Protocol, 根据广告model数据创建不同的广告类, 有没有demo呢? 有在TT空间下
 */

// MARK: 2. 抽象工厂模式(Abstract Factory Pattern)
/**
 * 利用多态性, 提供一个创建一系列相关或相互依赖对象的接口, 而无需指定它们具体的类.
 * 抽象工厂模式一般要满足:
 * 系统中有多个产品族, 而系统一次只可能消费其中一族产品.
 * 同属于同一个产品族的产品以其使用
 * e.g.:
 * 工厂A, 工厂B, 工厂C 都能生产盘子, 碗, 筷子...
 * 在创建的时候需要用不同的工厂的不同类去生产做不同的工作
 * 工厂A盘子, 工厂A碗, 工厂A筷子, 工厂B盘子......
 */

// MARK: 3. 单例模式(Singleton Pattern)
/**
 * 保证一个类仅有一个实例，并提供一个访问它的全局访问点
 * e.g.:
 * UIApplication, UIDevice ......
 */

// MARK: 4. 建造者模式
/**
 * 一般来说建造者模式有四个角色:
 1. 产品(product)
 2. 抽象建造者(Builder)
 3. 建造者(ConcreteBuilder)
 4. 指挥者(Director)
 * e.g.: 说不上来很复杂.
 * 需要创建一个房子
 * 房子: 可以认为是一个产品,
 * 有个抽象图纸,
 * 创建者: 盖房子的人,
 * 指挥者: 怎么盖这个房子的人
 */

// MARK: 5. 原型模式(Prototype Pattern)
/**
 * 用原型实例指定创建对象的种类, 并且通过拷贝这些原型创建新的对象
 * e.g.:
 * 深拷贝, 浅拷贝
 */

// MARK: - 2. 结构型模式

// MARK: 1. 适配器模式(Adapter Pattern)
/**
 * 将一个类的接口转换成客户希望的另外一个接口
 * 使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作.
 * e.g.:
 * MVVM 就是拿到后端的数据转成自己想要的ViewModel数据
 */

// MARK: 2. 装饰器模式(Decorator Pattern)
/**
 * 动态地给一个对象添加一些额外的职责.
 * 就增加功能来说, 装饰器模式比生成子类更为灵活.
 * e.g.:
 * swift extension, oc里的category
 */

// MARK: 3. 代理模式(Proxy Pattern)
/**
 * 为其他对象提供一种代理以控制对这个对象的访问
 * e.g.:
 * iOS很多delegate/ timer利用proxy 做弱引用
 */

// MARK: 4. 外观模式(Facade Pattern)
/**
 * 为子系统中的一组接口提供一个一致的界面,
 * 此模式定义了一个高层接口, 使得这个子系统更加容易使用
 * e.g.:
 * 皮肤
 */

// MARK: 5. 桥接模式(Bridge Pattern)
/**
 * 将抽象部分与它的实现部分分离, 使它们都可以独立地变化.
 * e.g.:
 * oc里的类型 桥接转换 stirng -> CFString
 */

// MARK: 6. 组合模式(Composite Pattern)
/**
 * 将对象组合成树形结构以表示“整体-部分”的层次结构,
 * 使得用户对单个对象和组合对象的使用具有一致性
 * e.g.:
 * Model 经常可见
 */

// MARK: 7. 享元模式(Flyweight Pattern)
/**
 * 减少内存使用量, 相似物件分享资讯, 共享部分状态, 放在外部资料结构, 需要时传递给享元
 * e.g.:
 * 底层的Framework
 */

// MARK: - 3. 行为型模式

// MARK: 1. 策略模式(Strategy Pattern)
/**
 * 定义一系列的算法，把它们一个个封装起来，并且使它们可相互替换
 * e.g.:
 * oc中的字符串NSString, NSArray 创建的时候根据内容数量不同不同的类型对象
 */

// MARK: 2. 模板方法模式(Template Method Pattern)
/**
 * 定义一个操作中的算法骨架，而将一些步骤延迟到子类中。
 * 模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
 * e.g.:
 * swift protocol 声明后 利用extension 给个默认实现, 在类遵守后还可以重写
 */

// MARK: 3. 观察者模式(Observer Pattern)
/**
 * 定义了一种一对多的依赖关系，让多个观察对象同时监听某一个主题对象，
 * 当主题对象发生变化时，它的所有观察者都会收到通知并更新自己
 * e.g.:
 * iOS 监听、通知
 */

// MARK: 4. 迭代器模式(Iterator Pattern)
/**
 * 提供一种方法顺序访问一个聚合对象中各个元素，而又不暴露该对象的内部表示
 * e.g.:
 * foreach
 */

// MARK: 5. 责任链模式(Chain of Responsibility Pattern)
/**
 * 为解除请求的发送者和接收者之间耦合，而使多个对象都有机会处理这个请求.
 * 将这些对象连成一条链，并沿着这条链传递该请求，直到有一个对象处理它为止
 * e.g.:
 * iOS 事件传递, hitTest, 找到最合适的view响应
 */

// MARK: 6. 命令模式(Command Pattern)
/**
 * 将一个请求封装成一个对象，从而使您可以用不同的请求对客户进行参数化；
 * 对请求排队或记录请求日志，以及支持可撤销的操作。
 * e.g.:
 * socket 就是最常见的命令模式
 */

// MARK: 7. 状态模式(State Pattern)
/**
 * 允许一个对象在其内部状态改变时改变它的行为，对象看起来似乎修改了它的类。
 * e.g.:
 * UIButton
 */

// MARK: 8. 备忘录模式(Memento Pattern)
/**
 * 在不破坏封装的前提下，捕获一个对象的内部状态，并在该对象之外保存这个状态。
 * 以后就可将该对象恢复到原先保存的状态
 * e.g.:
 * 项目中视频播放器播放过程中退到Home 暂停视频, 就是备忘录模式
 */

// MARK: 9. 访问者模式(Visitor Pattern)
/**
 * 表示一个作用于某个对象结构中的各元素的操作，
 * 它使您可以在不改变各元素类的前提下定义作用于这些元素的新操作
 * e.g.:
 *
 */

// MARK: 10. 中介者模式(Mediator Pattern)
/**
 * 用一个中介对象来封装一系列的对象交互。
 * 中介者使各对象不需要显式地相互引用，从而使其耦合松散，而且可以独立地改变它们之间的交互
 * e.g.:
 * NSTimer 利用中介者模式通过消息转发可以做到对象释放后timer 被释放不需要做invalided
 */

// MARK: 11. 解释器模式(Interpreter Pattern)
/**
 * 给定一个语言，定义它的文法的一种表示，并定义一个解释器，
 * 该解释器使用该表示来解释语言中的句子
 * e.g.:
 * 多语言
 */

// MARK: - Other型模式

// MARK: 1. 过滤器模式(Filter Pattern)
/**
 * 使用不同的标准来过滤一组对象，通过逻辑运算以解耦合条件。
 * e.g.:
 * 2进制 & |
 */

// MARK: 2. 混合模式(Mixin Pattern)
/**
 * ：将多个类的接口和实现组合到一个新的类中，以便达到多重继承的效果。
 混合模式提供了一种灵活的方式来增强类的功能，而又不需要使用多重继承
 * e.g.:
 * 多个类中的字段融合
 */

// MARK: 3. 发布-订阅模式(Publish-Subscribe Pattern)
/**
 * 定义了对象间的一种一对多的依赖关系，当一个对象的状态发生改变时，
 所有依赖于它的对象都将得到通知。
 * e.g.:
 * iOS 订阅通知(触发器)
 */

// MARK: 4. 重定向模式(Redirector Pattern)
/**
 * 为调试和性能监视而设计的一种模式，通过重定向(或拦截)来控制对对象的访问。
 * e.g.:
 * iOS web重定向
 */

// MARK: 5. 重试模式(Retry Pattern)
/**
 * 当一个操作失败时，重试模式会自动重新尝试该操作，直到成功为止。
 它通常用于与不可靠的资源或服务进行通信的系统中
 * e.g.:
 * 删除/ 同步数据失败后2次重试
 */

// MARK: 6. 规格模式(Specification Pattern)
/**
 * 将业务规则封装在一个对象中，这个对象可以被用于执行一系列的规则评估操作。
 * e.g.:
 * 同1个商品 定义不同价钱不同的表现
 */
